import cv2 as cv
import numpy as np


def big_image_binary(image):
    print(image.shape)
    ch = 200  # 每一块的高度
    cw = 200  # 每一块的宽度
    h, w = image.shape[:2]
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    for row in range(0, h, ch):  # 表示从0开始，一直到h-1（不包含h），步长为ch
        for col in range(0, w, cw):
            roi = gray[row:row+ch, col:col+cw]
            ret, dst = cv.threshold(roi, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
            gray[row:row + ch, col:col + cw] = dst
    return gray


def contours_demo(image):
    dst = cv.GaussianBlur(image, (3, 3), 0)  # 高斯模糊去噪
    binary = big_image_binary(dst)
    cv.imshow("binary image", binary)
    offset, contours, heriachy = cv.findContours(binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
    # image参数表示8位单通道图像矩阵，可以是灰度图，但更常用的是二值图像，一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像。
    # mode参数表示轮廓检索模式：
    #     ①CV_RETR_EXTERNAL：只检测最外围轮廓，包含在外围轮廓内的内围轮廓被忽略。
    #     ②CV_RETR_LIST：检测所有的轮廓，包括内围、外围轮廓，但是检测到的轮廓不建立等级关系，彼此之间独立，没有等级关系，这就意味着这个检索模式下不存在父轮廓或内嵌轮廓。
    #     ③CV_RETR_CCOMP：检测所有的轮廓，但所有轮廓只建立两个等级关系，外围为顶层，若外围内的内围轮廓还包含了其他的轮廓信息，则内围内的所有轮廓均归属于顶层。
    #     ④CV_RETR_TREE：检测所有轮廓，所有轮廓建立一个等级树结构，外层轮廓包含内层轮廓，内层轮廓还可以继续包含内嵌轮廓。
    # method参数表示轮廓的近似方法：
    #     ①CV_CHAIN_APPROX_NONE 存储所有的轮廓点，相邻的两个点的像素位置差不超过1，即max （abs (x1 - x2), abs(y2 - y1) == 1。
    #     ②CV_CHAIN_APPROX_SIMPLE压缩水平方向，垂直方向，对角线方向的元素，只保留该方向的终点坐标，例如一个矩形轮廓只需4个点来保存轮廓信息。
    #     ③CV_CHAIN_APPROX_TC89_L1，CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法。
    # contours参数是一个list，表示存储的每个轮廓的点集合。
    # hierarchy参数是一个list,list中元素个数和轮廓个数相同，每个轮廓contours[i]对应4个hierarchy元素
    # offset参数表示每个轮廓点移动的可选偏移量。
    for i, contour in enumerate(contours):
        cv.drawContours(image, contours, i, (0, 0, 255), 2)
        # image参数表示目标图像。
        # contours参数表示所有输入轮廓。
        # contourIdx参数表示绘制轮廓list中的哪条轮廓， 如果是负数，则绘制所有轮廓。
        # color参数表示轮廓的颜色。
        # thickness参数表示绘制的轮廓线条粗细，如果是负数，则绘制轮廓内部。
        # print(i)
    cv.imshow("contours", image)
    for i, contour in enumerate(contours):
        cv.drawContours(image, contours, i, (0, 0, 255), -1)
    cv.imshow("pcontours", image)


src = cv.imread('imgs/test009.jpg')
cv.namedWindow('input_image', cv.WINDOW_NORMAL)  # 设置为WINDOW_NORMAL可以任意缩放
cv.imshow('input_image', src)
contours_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
